using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

using Conscript;
using Conscript.Compiler;
using Conscript.Runtime;

namespace DungeonOfDespair
{
    public enum EnemyType
    {
        Troll,
        Lizard,
        Pig,
        Wizard,
        Boss
    }

    public class Enemy
        : Character, HostFunctionHandler
    {
        private static Script s_scriptTroll;
        private static Script s_scriptLizard;
        private static Script s_scriptPig;
        private static Script s_scriptWizard;
        private static Random s_random = new Random();

        private static Image GetSpriteSheet(EnemyType enemyType)
        {
            switch (enemyType)
            {
                case EnemyType.Troll:
                    return Properties.Resources.NPCTroll;
                case EnemyType.Lizard:
                    return Properties.Resources.NPCLizard;
                case EnemyType.Pig:
                    return Properties.Resources.NPCPig;
                default:
                    return Properties.Resources.NPCWizard;
            }
        }

        private Enemies m_enemies;
        private EnemyType m_enemyType;
        private ScriptContext m_scriptContext;
        private Player m_player;

        public Enemy(Enemies enemies, EnemyType enemyType)
            : base(GetSpriteSheet(enemyType))
        {
            m_enemies = enemies;
            m_enemyType = enemyType;
            m_player = m_enemies.Room.Dungeon.Player;

            ScriptManager scriptManager
                = enemies.Room.Dungeon.ScriptManager;

            switch (enemyType)
            {
                case EnemyType.Troll:
                    if (s_scriptTroll == null)
                        s_scriptTroll = new Script(scriptManager, "Troll.cns");
                    m_scriptContext = new ScriptContext(s_scriptTroll);
                    Health = 20;
                    break;
                case EnemyType.Lizard:
                    if (s_scriptLizard == null)
                        s_scriptLizard = new Script(scriptManager, "Lizard.cns");
                    m_scriptContext = new ScriptContext(s_scriptLizard);
                    Health = 40;
                    break;
                case EnemyType.Pig:
                    if (s_scriptPig == null)
                        s_scriptPig = new Script(scriptManager, "Pig.cns");
                    m_scriptContext = new ScriptContext(s_scriptPig);
                    Health = 60;
                    break;
                case EnemyType.Wizard:
                    if (s_scriptWizard == null)
                        s_scriptWizard = new Script(scriptManager, "Wizard.cns");
                    m_scriptContext = new ScriptContext(s_scriptWizard);
                    Health = 100;
                    break;
                case EnemyType.Boss:
                    Health = 1000;
                    break;
            }

            if (m_scriptContext != null)
            {
                m_scriptContext.InterruptOnHostfunctionCall = true;
                m_scriptContext.Handler = this;
            }

            Speed = 2;
            m_bActive = false;
        }

        public void Reset()
        {
            m_bActive = true;
            X = s_random.Next(200, 440);
            Y = s_random.Next(160, 320);

            switch (m_enemyType)
            {
                case EnemyType.Troll: Health = 20; break;
                case EnemyType.Lizard: Health = 40; break;
                case EnemyType.Pig: Health = 60; break;
                case EnemyType.Wizard: Health = 100; break;
                case EnemyType.Boss: Health = 1000; break;
            }
        }

        public override void Update()
        {
            base.Update();
            if (!Moving && m_scriptContext != null)
                m_scriptContext.Execute();
        }

        public object OnHostFunctionCall(String strFunctionName, List<object> listParameters)
        {
            if (strFunctionName == "GetRandom")
            {
                int iMin = (int)listParameters[0];
                int iMax = (int)listParameters[1];
                return s_random.Next(iMin, iMax);
            }
            else if (strFunctionName == "Move")
            {
                int iDeltaX = (int)listParameters[0];
                int iDeltaY = (int)listParameters[1];
                Move(iDeltaX, iDeltaY);
            }
            else if (strFunctionName == "SetDirection")
            {
                Direction = (EntityDirection)(int)listParameters[0];
            }
            else if (strFunctionName == "SetAutomaticDirection")
            {
                AutomaticDirection = (bool)listParameters[0];
            }
            else if (strFunctionName == "GetPosition")
            {
                AssociativeArray associativeArrayPosition = new AssociativeArray();
                associativeArrayPosition["X"] = this.X;
                associativeArrayPosition["Y"] = this.Y;
                return associativeArrayPosition;
            }
            else if (strFunctionName == "GetPlayerPosition")
            {
                AssociativeArray associativeArrayPosition = new AssociativeArray();
                associativeArrayPosition["X"] = m_player.X;
                associativeArrayPosition["Y"] = m_player.Y;
                return associativeArrayPosition;
            }
            else if (strFunctionName == "CastSpell")
            {
                Image imageSpell = Properties.Resources.EnemySpell;
                int iDamage = m_enemyType == EnemyType.Wizard ? 40 : 20;
                Spell spell = new Spell(m_enemies.Room.Spells, imageSpell, false, iDamage, Direction);
                spell.X = X;
                spell.Y = Y - 30;
                m_enemies.Room.Spells.Add(spell);
                return null;
            }

            return null;
        }
    }
}
